//      libsvm_main.cc
//      
//      Copyright 2012 tqlong <tqlong@espada>
//      
//      This program is free software; you can redistribute it and/or modify
//      it under the terms of the GNU General Public License as published by
//      the Free Software Foundation; either version 2 of the License, or
//      (at your option) any later version.
//      
//      This program is distributed in the hope that it will be useful,
//      but WITHOUT ANY WARRANTY; without even the implied warranty of
//      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//      GNU General Public License for more details.
//      
//      You should have received a copy of the GNU General Public License
//      along with this program; if not, write to the Free Software
//      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
//      MA 02110-1301, USA.

/* example run
 */

#include <iostream>
#include <boost/program_options.hpp>
#include <boost/date_time/posix_time/posix_time.hpp> 

#include "helper/stl_helper.h"
#include "helper/ublas_helper.h"
#include "helper/ml_data.h"
#include "helper/rand_helper.h"

#include "libsvm/libsvm.h" 

namespace po = boost::program_options;
po::options_description desc("Allowed options");
po::variables_map vm;

void process_options(int argc, char** argv);
void usage(int exitcode = 0);

void read_data();

boost::posix_time::ptime time_start(boost::posix_time::microsec_clock::local_time());

boost::posix_time::time_duration duration() 
{
  return boost::posix_time::microsec_clock::local_time() - time_start;
}

boost::posix_time::ptime now() 
{
  return boost::posix_time::microsec_clock::local_time();
}

int main(int argc, char** argv)
{
  //MSG("Matching Pursuit for General Loss ... ");

  process_options(argc, argv);

  if (vm.count("help"))
    usage();
  else if (vm.count("read"))
    read_data();
  else
    usage();

  MSG("Duration = " << duration());
}

void process_options(int argc, char** argv)
{
  desc.add_options()
    ("help", "produce this usage")
    ("input", po::value<std::string>(), "input file")
    ("output", po::value<std::string>(), "output file")
    ("verbose", "print debug information")

    // likelihood computation
    ("ll", po::value<std::vector<std::string> >(), "sequence files to compute log-likelihood")
    ("llout", po::value<std::vector<std::string> >(), "likelihood output files")
    ("fom_ll",  "Compute likelihood of FOM model")
    ("imm_xi_ll", "Compute likelihood of IMM model (chi-square)")
    
    // Accuracy calculation
    ("negneg", po::value<std::string>(), "negative set, negative model output")
    ("negpos", po::value<std::string>(), "negative set, positive model output")
    ("posneg", po::value<std::string>(), "positive set, negative model output")
    ("pospos", po::value<std::string>(), "positive set, positive model output")

    // sequence set manipulation
    ("length", po::value<int>(), "fixed length to cut")
    ("ratio", po::value<double>()->default_value(0.5), "ratio of train set / all")

    // VOM param
    ("order", po::value<std::vector<int> >(), "FOM orders")
    ("period", po::value<int>(), "periodic (1, 3)")

    // IMM param
    ("imm_T", po::value<int>(), "Threshold for number of occurence (IMM chi-square)")

    // output options
    ("fom_stats", po::value<std::string>(), "fom statistics file")

    //JOB TYPE
    ("read", "read data file\n--input [--output]")
    ("fom", "Build FOM\n--input [--output] [--order]+ --periodic")
    ("fix_length", "split long sequence to fixed length\n--input [--output] --length")
    ("train_test", "split set of sequences to train set and test seth\n --input [--train] [--test] --ratio")
    ("accuracy", "--negneg --negpos --pospos --posneg --output")
    ;
  po::store(po::parse_command_line(argc, argv, desc), vm);
  po::notify(vm);
}

void usage(int exitcode)
{
  std::cout << desc << std::endl;
  exit(exitcode);
}

void read_data()
{
  std::string inputFile = vm["input"].as<std::string>();
  typedef DataTable<sparse_vec_t, sparse_matrix_t> Data;
  //typedef DataTable<vec_t, matrix_t> Data;

  Data D;
  DataReader::read_libsvm(inputFile, D, true); // add a bias term
  MSG("sz(D)=" << sz(D) << " dim(D)=" << D.dim());

  struct svm_problem prob;
  libsvm_convert_data_table<Data>(prob, D);
}

